{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 加载数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "# os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"1\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n",
      "f:\\anaconda\\envs\\py37\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:526: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n",
      "f:\\anaconda\\envs\\py37\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:527: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n",
      "f:\\anaconda\\envs\\py37\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:528: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n",
      "f:\\anaconda\\envs\\py37\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:529: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n",
      "f:\\anaconda\\envs\\py37\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:530: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n",
      "f:\\anaconda\\envs\\py37\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:535: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "from keras.utils import np_utils\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Dropout\n",
    "\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_train = np.load('E:/IDS/alldata/12/RUS+SMOTE/label_2/data.npy')\n",
    "y_train = np.load('E:/IDS/alldata/12/RUS+SMOTE/label_2/label.npy')\n",
    "\n",
    "\n",
    "x_test = np.load('E:/IDS/alldata/12/test/data.npy')\n",
    "y_test = np.load('E:/IDS/alldata/12/test/label_2.npy')\n",
    "\n",
    "x_val = np.load('E:/IDS/alldata/12/val/data.npy')\n",
    "y_val = np.load('E:/IDS/alldata/12/val/label_2.npy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1778030, 12) (1778030, 1) (508012, 12) (508012, 1) (254005, 12) (254005, 1)\n"
     ]
    }
   ],
   "source": [
    "print(x_train.shape,y_train.shape,x_test.shape,y_test.shape,x_val.shape,y_val.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 对类标签进行one-hot编码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape of data (BEFORE encode): (1778030, 1)\n",
      "Shape of data (AFTER  encode): (1778030, 2)\n",
      "\n",
      "Shape of data (BEFORE encode): (508012, 1)\n",
      "Shape of data (AFTER  encode): (508012, 2)\n",
      "\n",
      "Shape of data (BEFORE encode): (254005, 1)\n",
      "Shape of data (AFTER  encode): (254005, 2)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from keras.utils import to_categorical\n",
    "def encode(data):\n",
    "    print('Shape of data (BEFORE encode): %s' % str(data.shape)) #编码之前标签的形状\n",
    "    encoded = to_categorical(data)\n",
    "    print('Shape of data (AFTER  encode): %s\\n' % str(encoded.shape))  #编码之后标签的形状\n",
    "    return encoded\n",
    "\n",
    "y_train_onehot = encode(y_train)\n",
    "y_test_onehot = encode(y_test)\n",
    "y_val_onehot = encode(y_val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# MLP模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From f:\\anaconda\\envs\\py37\\lib\\site-packages\\tensorflow\\python\\framework\\op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Colocations handled automatically by placer.\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "dense_1 (Dense)              (None, 128)               1664      \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 128)               16512     \n",
      "_________________________________________________________________\n",
      "dense_3 (Dense)              (None, 64)                8256      \n",
      "_________________________________________________________________\n",
      "dense_4 (Dense)              (None, 32)                2080      \n",
      "_________________________________________________________________\n",
      "dense_5 (Dense)              (None, 2)                 66        \n",
      "=================================================================\n",
      "Total params: 28,578\n",
      "Trainable params: 28,578\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "from keras import regularizers #添加权重正则化模块\n",
    "\n",
    "model = Sequential()\n",
    "model.add(Dense(input_dim = 12,\n",
    "                units = 128,\n",
    "              \n",
    "                activation = 'relu'))  #units =  该层的神经单元结点数。\n",
    "\n",
    "\n",
    "model.add(Dense(units = 128,\n",
    "           \n",
    "                activation = 'relu'))\n",
    "\n",
    "model.add(Dense(units = 64,\n",
    "             \n",
    "                activation = 'relu'))\n",
    "\n",
    "\n",
    "model.add(Dense(units = 32,\n",
    "              \n",
    "                activation = 'relu'))\n",
    "\n",
    "\n",
    "model.add(Dense(units = 2,\n",
    "                activation = 'softmax'))\n",
    "\n",
    "print(model.summary())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From f:\\anaconda\\envs\\py37\\lib\\site-packages\\tensorflow\\python\\ops\\math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use tf.cast instead.\n",
      "Train on 1778030 samples, validate on 254005 samples\n",
      "Epoch 1/50\n",
      " - 8s - loss: 0.0316 - acc: 0.9901 - val_loss: 0.0317 - val_acc: 0.9852\n",
      "Epoch 2/50\n",
      " - 8s - loss: 0.0305 - acc: 0.9911 - val_loss: 0.0358 - val_acc: 0.9858\n",
      "Epoch 3/50\n",
      " - 8s - loss: 0.0344 - acc: 0.9913 - val_loss: 0.0388 - val_acc: 0.9839\n",
      "Epoch 4/50\n",
      " - 8s - loss: 0.0340 - acc: 0.9914 - val_loss: 0.0329 - val_acc: 0.9864\n",
      "Epoch 5/50\n",
      " - 8s - loss: 0.0338 - acc: 0.9915 - val_loss: 0.0313 - val_acc: 0.9864\n",
      "Epoch 6/50\n",
      " - 8s - loss: 0.0335 - acc: 0.9915 - val_loss: 0.0318 - val_acc: 0.9864\n",
      "Epoch 7/50\n",
      " - 8s - loss: 0.0335 - acc: 0.9916 - val_loss: 0.0317 - val_acc: 0.9863\n",
      "Epoch 8/50\n",
      " - 8s - loss: 0.0347 - acc: 0.9915 - val_loss: 0.0294 - val_acc: 0.9864\n",
      "Epoch 9/50\n",
      " - 8s - loss: 0.0328 - acc: 0.9916 - val_loss: 0.0325 - val_acc: 0.9871\n",
      "Epoch 10/50\n",
      " - 8s - loss: 0.0325 - acc: 0.9918 - val_loss: 0.0324 - val_acc: 0.9872\n",
      "Epoch 11/50\n",
      " - 8s - loss: 0.0680 - acc: 0.9894 - val_loss: 0.0428 - val_acc: 0.9866\n",
      "Epoch 12/50\n",
      " - 8s - loss: 0.0378 - acc: 0.9914 - val_loss: 0.0321 - val_acc: 0.9872\n",
      "Epoch 13/50\n",
      " - 8s - loss: 0.0335 - acc: 0.9916 - val_loss: 0.0315 - val_acc: 0.9871\n",
      "Epoch 14/50\n",
      " - 8s - loss: 0.0330 - acc: 0.9916 - val_loss: 0.0308 - val_acc: 0.9852\n",
      "Epoch 15/50\n",
      " - 8s - loss: 0.0332 - acc: 0.9916 - val_loss: 0.0321 - val_acc: 0.9873\n",
      "Epoch 16/50\n",
      " - 8s - loss: 0.0329 - acc: 0.9918 - val_loss: 0.0308 - val_acc: 0.9864\n",
      "Epoch 17/50\n",
      " - 8s - loss: 0.0331 - acc: 0.9918 - val_loss: 0.0322 - val_acc: 0.9864\n",
      "Epoch 18/50\n",
      " - 8s - loss: 0.0331 - acc: 0.9916 - val_loss: 0.0312 - val_acc: 0.9864\n",
      "Epoch 19/50\n",
      " - 8s - loss: 0.0337 - acc: 0.9916 - val_loss: 0.0330 - val_acc: 0.9873\n",
      "Epoch 20/50\n",
      " - 8s - loss: 0.0326 - acc: 0.9918 - val_loss: 0.0320 - val_acc: 0.9868\n",
      "Epoch 21/50\n",
      " - 8s - loss: 0.0326 - acc: 0.9918 - val_loss: 0.0319 - val_acc: 0.9864\n",
      "Epoch 22/50\n",
      " - 8s - loss: 0.0338 - acc: 0.9913 - val_loss: 0.0321 - val_acc: 0.9852\n",
      "Epoch 23/50\n",
      " - 8s - loss: 0.0364 - acc: 0.9913 - val_loss: 0.0333 - val_acc: 0.9872\n",
      "Epoch 24/50\n",
      " - 8s - loss: 0.0328 - acc: 0.9917 - val_loss: 0.0313 - val_acc: 0.9865\n",
      "Epoch 25/50\n",
      " - 8s - loss: 0.0328 - acc: 0.9917 - val_loss: 0.0292 - val_acc: 0.9875\n",
      "Epoch 26/50\n",
      " - 8s - loss: 0.0330 - acc: 0.9915 - val_loss: 0.0325 - val_acc: 0.9872\n",
      "Epoch 27/50\n",
      " - 8s - loss: 0.0326 - acc: 0.9918 - val_loss: 0.0282 - val_acc: 0.9872\n",
      "Epoch 28/50\n",
      " - 8s - loss: 0.0404 - acc: 0.9913 - val_loss: 0.0527 - val_acc: 0.9852\n",
      "Epoch 29/50\n",
      " - 8s - loss: 0.0430 - acc: 0.9912 - val_loss: 0.0309 - val_acc: 0.9864\n",
      "Epoch 30/50\n",
      " - 8s - loss: 0.0328 - acc: 0.9918 - val_loss: 0.0343 - val_acc: 0.9872\n",
      "Epoch 31/50\n",
      " - 8s - loss: 0.0325 - acc: 0.9919 - val_loss: 0.0324 - val_acc: 0.9872\n",
      "Epoch 32/50\n",
      " - 8s - loss: 0.0323 - acc: 0.9919 - val_loss: 0.0302 - val_acc: 0.9872\n",
      "Epoch 33/50\n",
      " - 8s - loss: 0.0326 - acc: 0.9917 - val_loss: 0.0311 - val_acc: 0.9873\n",
      "Epoch 34/50\n",
      " - 8s - loss: 0.0324 - acc: 0.9918 - val_loss: 0.0343 - val_acc: 0.9866\n",
      "Epoch 35/50\n",
      " - 8s - loss: 0.0326 - acc: 0.9918 - val_loss: 0.0292 - val_acc: 0.9872\n",
      "Epoch 36/50\n",
      " - 8s - loss: 0.0325 - acc: 0.9917 - val_loss: 0.0311 - val_acc: 0.9865\n",
      "Epoch 37/50\n",
      " - 8s - loss: 0.0325 - acc: 0.9918 - val_loss: 0.0303 - val_acc: 0.9872\n",
      "Epoch 38/50\n",
      " - 8s - loss: 0.0317 - acc: 0.9919 - val_loss: 0.0314 - val_acc: 0.9872\n",
      "Epoch 39/50\n",
      " - 8s - loss: 0.0329 - acc: 0.9916 - val_loss: 0.0307 - val_acc: 0.9865\n",
      "Epoch 40/50\n",
      " - 8s - loss: 0.0324 - acc: 0.9918 - val_loss: 0.0302 - val_acc: 0.9873\n",
      "Epoch 41/50\n",
      " - 8s - loss: 0.0321 - acc: 0.9919 - val_loss: 0.0300 - val_acc: 0.9874\n",
      "Epoch 42/50\n",
      " - 8s - loss: 0.0318 - acc: 0.9918 - val_loss: 0.0303 - val_acc: 0.9873\n",
      "Epoch 43/50\n",
      " - 8s - loss: 0.0321 - acc: 0.9918 - val_loss: 0.0309 - val_acc: 0.9865\n",
      "Epoch 44/50\n",
      " - 8s - loss: 0.0320 - acc: 0.9918 - val_loss: 0.0292 - val_acc: 0.9873\n",
      "Epoch 45/50\n",
      " - 8s - loss: 0.0318 - acc: 0.9919 - val_loss: 0.0308 - val_acc: 0.9864\n",
      "train_time: 349.6136546134949\n"
     ]
    }
   ],
   "source": [
    "import keras\n",
    "#保存最佳模型\n",
    "import time\n",
    "time_start = time.time()\n",
    "\n",
    "callback_list = [keras.callbacks.EarlyStopping(monitor='val_acc',patience=30,),  #如果精度在多于3轮的时间内不再改善，中断训练\n",
    "                keras.callbacks.ModelCheckpoint(filepath='my_model.h5',monitor='val_acc',save_best_only=True,)]\n",
    "\n",
    "model.compile(loss = \"categorical_crossentropy\",optimizer = \"nadam\", metrics = [\"accuracy\"])#损失函数，优化器，精度\n",
    "history = model.fit(x = x_train,y = y_train_onehot,\n",
    "                epochs = 100,\n",
    "                batch_size = 256,\n",
    "                verbose = 2,\n",
    "                callbacks=callback_list,\n",
    "                validation_data=(x_val, y_val_onehot) )\n",
    "\n",
    "time_end = time.time()\n",
    "train_time = time_end - time_start\n",
    "print(\"train_time:\",train_time)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "508012/508012 [==============================] - 4s 7us/step\n",
      "test_loss =  0.031169582333884414 test_accuracy =  0.986506224262419\n"
     ]
    }
   ],
   "source": [
    "#计算最终的测试精度\n",
    "scores = model.evaluate(x_test, y_test_onehot)\n",
    "print(\"test_loss = \", scores[0],\"test_accuracy = \", scores[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.save('E:/IDS/alldata/12/RUS+SMOTE/label_2/MLP_RUS_2.h5')#保存模型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 绘制混淆矩阵和热力图 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "test_time: 2.7127366065979004\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "time_start = time.time()\n",
    "y_pred_onehot  = model.predict(x_test)  #返回的是在类别上的概率分布\n",
    "\n",
    "y_pred_label=np.argmax(y_pred_onehot,axis=1)#概率最大的类别就是预测类别\n",
    "\n",
    "time_end = time.time()\n",
    "test_time = time_end - time_start\n",
    "print(\"test_time:\",test_time)\n",
    "\n",
    "# np.savetxt(\"/home/hll/IDS/cicdata/77_2/pre/MLP_y_pred_ADASYN.txt\",y_pred_label)  #保存预测标签\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_true_onehot=y_test_onehot\n",
    "y_true_label=np.argmax(y_true_onehot,axis=1)\n",
    "# np.savetxt(\"/home/hll/IDS/cicdata/77_2/pre/MLP_y_true_ADASYN.txt\",y_true_label)  #保存真实标签"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1200x1200 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# -*-coding:utf-8-*-\n",
    "from sklearn.metrics import confusion_matrix\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "labels = ['Normal','Attack']\n",
    "          \n",
    "y_pred  = y_pred_label  #读取真实标签和预测标签的值\n",
    "y_true = y_true_label\n",
    "\n",
    "\n",
    "tick_marks = np.array(range(len(labels))) + 0.5\n",
    "\n",
    "def plot_confusion_matrix(cm, title='Confusion Matrix', cmap=plt.cm.binary):\n",
    "    plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)  #cmap=cmap是黑白色\n",
    "    plt.title(title)\n",
    "    plt.colorbar()\n",
    "    xlocations = np.array(range(len(labels)))\n",
    "    plt.xticks(xlocations, labels, rotation=90)\n",
    "    plt.yticks(xlocations, labels)\n",
    "    plt.ylabel('True label')\n",
    "    plt.xlabel('Predicted label')\n",
    "\n",
    "\n",
    "cm = confusion_matrix(y_true, y_pred)  #cm是混淆矩阵\n",
    "np.set_printoptions(precision=2)  #保留两位小数\n",
    "cm_normalized = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]  #混淆矩阵的每个元素的值（0-1）\n",
    "\n",
    "plt.figure(figsize=(10, 10), dpi=120)\n",
    "\n",
    "ind_array = np.arange(len(labels))\n",
    "x, y = np.meshgrid(ind_array, ind_array)\n",
    "\n",
    "for x_val, y_val in zip(x.flatten(), y.flatten()):\n",
    "    c = cm_normalized[y_val][x_val]\n",
    "    if c > 0.001:\n",
    "        plt.text(x_val, y_val, \"%0.2f\" % (c,), color='red', fontsize=13, va='center', ha='center')\n",
    "# offset the tick\n",
    "plt.gca().set_xticks(tick_marks, minor=True)\n",
    "plt.gca().set_yticks(tick_marks, minor=True)\n",
    "plt.gca().xaxis.set_ticks_position('none')\n",
    "plt.gca().yaxis.set_ticks_position('none')\n",
    "plt.grid(True, which='minor', linestyle='-')\n",
    "plt.gcf().subplots_adjust(bottom=0.15)\n",
    "\n",
    "plot_confusion_matrix(cm_normalized, title='Normalized confusion matrix')  #规范化的混淆矩阵\n",
    "#plt.savefig('confusion_matrix.png', format='png')  #保存结果图\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[437015   6740]\n",
      " [   115  64142]]\n"
     ]
    }
   ],
   "source": [
    "print(cm)  #输出混淆矩阵具体的数值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 二分类评价指标"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "acc: 0.986506224262419\n",
      "DR: 0.9982103117170114\n",
      "FPR: 0.015188561255647824\n",
      "recall： 0.9982103117170114\n",
      "precision: 0.9049123896052594\n",
      "f1: 0.9492744507507085\n"
     ]
    }
   ],
   "source": [
    "TP=cm[1,1]\n",
    "FP=cm[0,1]\n",
    "FN=cm[1,0]\n",
    "TN=cm[0,0]\n",
    "\n",
    "acc = (TP+TN)/(TP+TN+FP+FN)\n",
    "print(\"acc:\",acc)\n",
    "\n",
    "DR = TP/(TP+FN)  #检出率（查准率）\n",
    "print(\"DR:\",DR)\n",
    "\n",
    "FPR = FP/(FP+TN)  #假阳性率\n",
    "print(\"FPR:\",FPR)\n",
    "\n",
    "recall =TP/(TP+FN)\n",
    "print(\"recall：\",recall)  #召回率\n",
    "\n",
    "precision = TP/(TP+FP)\n",
    "print(\"precision:\",precision)\n",
    "\n",
    "f1 = (2*precision*recall)/(precision+recall)\n",
    "print(\"f1:\",f1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 绘制二分类ROC曲线"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plotRUC(yt, ys, title=None):\n",
    "    '''\n",
    "    绘制ROC-AUC曲线\n",
    "    :param yt: y真值\n",
    "    :param ys: y预测值\n",
    "    '''\n",
    "    from sklearn import metrics\n",
    "    from matplotlib import pyplot as plt\n",
    "    f_pos, t_pos, thresh = metrics.roc_curve(yt, ys)\n",
    "    auc_area = metrics.auc(f_pos, t_pos)\n",
    "    print('auc_area: {}'.format(auc_area))\n",
    "\n",
    "    plt.plot(f_pos, t_pos, 'darkorange', lw=2, label='AUC = %.2f' % auc_area)\n",
    "    plt.legend(loc='lower right')\n",
    "\n",
    "    plt.title('ROC-AUC curve for %s' % title)\n",
    "    plt.ylabel('True Pos Rate')\n",
    "    plt.xlabel('False Pos Rate')\n",
    "    \n",
    "    plt.grid(linestyle='--')  #网格线\n",
    "    \n",
    "#     plt.savefig('/home/hll/IDS/cicdata/77_2/pre/MLP_12_2_ADASYN.png',format='png')\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "auc_area: 0.9915108752306817\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEWCAYAAABrDZDcAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nO2dfXxdZZXvv6tJG1KSQJvS1jYpSSUtpIGUNLchmmkZQK2MgoyA9SIvjmNn9OILOjiMozNcR68OOhcVmYvIOAJKK4OKVUFU6ItxQiEEg02wL7ShTV/SkgST0DZpknX/2PucnqRJzkmy9zlJnvX9fPYnz97n2c9ev7NP9trPet5EVTEMwzDcZVqqDTAMwzBSizkCwzAMxzFHYBiG4TjmCAzDMBzHHIFhGIbjmCMwDMNwHHMEhmEYjmOOwDAmECKyVEReFJFOEfl4qu0x3MAcgRFFRJpE5LiIdInIYRH5nohkDcrzFhF5xn9Q/UlEfiYixYPy5IjI10Vkn1/Wbn9/Tpzr3yIiKiLXD3G8ehh7r4jZXykiT4jI6yLSJiLPicgHx/ZtpIzPAJtVNVtVvznewkTkTv87/fig45/0j9/p718qIs3DlPE9Eenx72WbiPxaRM6Pc937/PyRrVtEOmM+7xq09YnIPePVa4wNcwTGYN6tqlnAcuBi4B8iH4hIJfAr4KfAAqAQqAd+JyKL/TwzgKeBZcAaIAd4C9AKrIxz7ZuBNv/vqPBtewbYApwH5AIfAd452rJGed30gIs8F2gI2JadnP6d3uQfT5S7/N9FHnAE+N5ImVX1b1U1K7IB64H/ivk89rN5wPHYz43kYo7AGBJVPQw8hecQItwFPKSq31DVTlVtU9XPAc8Cd/p5bgIWAdeoaqOq9qvqEVX9F1V9Yrjrici5wGpgHfAOEZk3SpO/Cjyoqv+qqq+pxwuqev1wJ4jIh0XkZb920ygiZf5xFZHzYvJ9T0S+6KcvFZFmEfl7ETkM/Kdfxrti8qeLyGsx5V0iIv/t11TqReTSYex5Bvhz4Fv+W/ISETlLRB4SkaMi8qqIfE5Epvn5bxGR34nI3SLSxql7MJjngZkissw/bxmQ6R8fFap6DHgEKEn0HBE5E3gv8OAwWa7Fcy6/Ha09RjCYIzCGRETy8N6md/v7M/He7Id6a3sUeJufvgL4pap2jfKSNwG1qvoj4GXghlHYOhOoBB4bxTnX4T04b8KrtVyFV2tJhPnAbLy393V4b7vvj/n8HcBrqlonIguBXwBf9M/5O+BHInLO4EJV9TK8h+Gt/tvyTuAe4CxgMZ6jvAmIDXdVAHuAucCXRrD5Yf9c8GoHDyWodQB+qPAG4MVRnPZe4CiwdZjPb8Z7wbCJz1KEOQJjMI/7sdz9eG9p/+wfn433ezk0xDmHgEj8P3eYPPG4Ce9NE//vaMJDs0awbTj+Gi/c8bxfe9itqq8meG4/8M+q2q2qx317r/IdEsD/5JSWDwBPqOoTfu3o10AtcGW8i4hIGvA+4B/8GlgT8G/AjTHZDqrqPara69syHN8H3i8i04G1/v5o+DsReR3vxSALuGUU5w77oBeRRXgObrjagpEEzBEYg3mPqmYDlwLnc+oB3473AHzTEOe8CXjNT7cOkwcAEbkhpoHwSf/YW/HaGzb42R4BLhSRSFiqF5g+RHHTgZNxbBuOfOCVUeSP5aiqnojsqOpuvFrMu31ncBWnHMG5wHV+WOh1/2FalaCtc4AZQKyDehVYGLO/PxGDVXUf3kP8/wC7VDWh82L4mqqerarzVfUqVU3ouxORfLwH/XA1kJuAalXdO0p7jAAxR2AMiapuwWsQ/Jq//wZQA1w3RPbr8RqIAX6DF+M/c5hyfxDTUBhpyL0ZEOD3ftx9m388EsrYBywSEYmU4z9w5wKv+nHrGrwQRKLsB948zGfHgJkx+/MHyxjinEh46Gqg0XcOkes87D9EI9uZqvqVBGx8Dc/RnRtzbBFwII4tw/EQ8GnGGBYaIzcB/62qe0b43GoDKcYcgTESXwfeFvNmfgdws4h8XESyRWSW34haCfxvP8/DeA+/H4nI+SIyTURyReSzInJaOEREzsBzJOvwGqYj28eAG/yeMNuAE8AdInKG72S+ghdiibwtfwa4RURuF5Fcv+xSEdnA0DyAF+5YIR7n+Q3WAL8H/qeIpInIGrw32nhsAN6O11PpkZjj38erKbzDL+8Mv8E5L16BqtqH1/7yJf/7Phf4FKMP60T4oW/jo8Nl8O2L3WS4vAlyE8P0MBKRt+DVbqy3UIoxR2AMi6oexXt7/Ly/X43XEPqXePH4V/G6mFap6i4/Tzdeg/EfgV8DHcBzeGGObZzOe/C6Dj6kqocjG/AfQBqwxi/zL/DCVc14jaMLgOsjcWdV/W/gMn/b4/eiuR8YsqeSqv4XXuPqI0An8DheOwjAJ4B3A6/jNYw+nsB3dQivVvIWvAdu5Ph+vFrCZ/EaTPcDt5P4/97HgDd8zdW+vd9N8NzBNh5X1d+M0JawEO9exG7D1Zri4nfpzWP4B/3NwI9VtXOYz40kIdZQbxiG4TZWIzAMw3AccwSGYYwJEXlyiKkiukTks6m2zRgdFhoyDMNwnKDnSQmdOXPmaEFBwZjO7enpYcaMGcEaNMExzW5gmt1gPJpfeOGF11T1tBHtMAkdQUFBAbW1tWM6d/PmzVx66aXBGjTBMc1uYJrdYDyaRWTYkfNOtRGUlpam2oSkY5rdwDS7QVianXIEnZ3udVc2zW5gmt0gLM1OOYI9e4Yb5T51Mc1uYJrdICzNTjkCwzAM43SccgRj7W00mTHNbmCa3SAszaE5AhH5rogcEZHtw3wuIvJN8dazfSmymlOYzJ49O36mKYZpdgPT7AZhaQ6zRvA9vDVrh+OdQJG/rQP+X4i2AFBXVxf2JSYcptkNTLMbhKU5tHEEqrpVRApGyHI1p1YtelZEzhaRN/mzOCaHg8/C0d+f2h8wylqHOT7SZ2PIN9ayEyxv0aFXYFtNMNcN83tI+Lrxz1ncvB82/3x4G5L2/Yd7b2M/W3roIPzyodOOB1F20LYGVXbJa6/B63MSLy8V/48Bf/8F/YvxJuENllQOKFvIwNWVmv1jpzkCEVmHV2tgwYIFbN68GYDFixeTnZ1NfX09ALm5uSxbtoytW72lUdPT06mqqqKuro6Ojg6OHz9OV1cXLS0tHGzayVvrr2aangxRYupZDHAw1VYkl0UALam2Irm8CRJfcXmKMAfgT6m2IrnMyBH27ds3quceQHl5+YjlhjrXkF8j+Lmqlgzx2S+AL/tz3CMiTwOfUdUXRiqzvLxcxzqyeACdB+D+PEifCcU3DvxswFocw6VHyDfs+YmeM8J1R8o3lrLHYmuYZY/pewig7FTcl4Svm8SyJ9PvMxW//VT/PjPPgdwLGAsi8oKqDukRUlkjaMZbNzZCHiG/u27ZsoXVq/3Fpvp7vL8z58Lb7gvzsilly5YtrF6VyAJbU4cB99kRTLMbeJrH5ghGIpXdRzcCN/m9hy4B/hR2+8CA2k+f7wjSpvakVS7OLmua3cA0B0doNQIRWY/XqjFHRJqBfwamA6jqfXhLCF4J7MZbLPyDYdkSY9OpHUccwfiXnJ18mGY3MM0BljvZvGpgbQQtL8D3y2FuGdw4YrOEYRjGpGekNgKnRhZHWtkBZ2oEAzQ7gml2A9McHE45gvb29lM7jjiCAZodwTS7gWkODqccwQAijmDa1HYEhmEY8XDKEZSVxUxn1O9GjWCAZkcwzW5gmoPDKUfQ1tZ2aseR0NAAzY5gmt3ANAeHU46gqanp1I4joaEBmh3BNLuBaQ4OpxzBABwJDRmGYcTDKUewePHiUzuOhIYGaHYE0+wGpjk4nHIE2dnZp3YccQQDNDuCaXYD0xwcTjmCAYMx+t1oI7BBN25gmt3ABpQFjSM1AsMwjHg45Qhyc3NP7TjiCAZodgTT7AamOTiccgTLli07teNI99EBmh3BNLuBaQ4OpxxBZCk3wJnuowM0O4JpdgPTHBxOOYIBOBIaMgzDiIdTjiA9PWYdHkdCQwM0O4JpdgPTHBzuLkzz67+Bl+6HK+6D0r8Zf3mGYRgTGFuYxqeuru7UjiOhoQGaHcE0u4FpDg6nHEFHR8epHUccwQDNjmCa3cA0B4dTjmAAjowsNgzDiIdTjqC8PCY85kiNYIBmRzDNbmCag8MpR9DS0nJqxxFHMECzI5hmNzDNweGUI9i/f/+pHUdCQwM0O4JpdgPTHBxOOYIBOFIjMAzDiIdTjqCoqOjUjiOOYIBmRzDNbmCag8MpR5CRkXFqx5GRxQM0O4JpdgPTHBxOOYLt27ef2nFk0rkBmh3BNLuBaQ4OpxzBABwJDRmGYcTDKUcwd+7cUzuOOIIBmh3BNLuBaQ4OpxzBkiVLTu040n10gGZHMM1uYJqDwylHUF1dfWrHkRrBAM2OYJrdwDQHR6iOQETWiMgOEdktIncM8fkiEdkkIi+KyEsicmWY9gzAEUdgGIYRj9AcgYikAfcC7wSKgfeLSPGgbJ8DHlXVi4G1wL+HZQ8M6nrlSGjIuti5gWl2g8nYfXQlsFtV96hqD7ABuHpQHgVy/PRZwMEQ7aGystK/qsbUCKaHecmUE9XsEKbZDUxzcIS51ttCIHZijGagYlCeO4FficjHgDOBK4YqSETWAesAFixYwObNmwFYvHgx2dnZ1NfXA5Cbm8uyZcuiCzynp6dTVVVFXV0dHR0dHDt2jFWrVtFyqJk3A/2kcejgITIyMqL9c+fOncuSJUuisbiMjAwqKyupra2lq6sLgIqKCpqbmzlw4AAAS5cuJS0tjcbGRgDmz59PYWEhNTU1AGRmZlJRUcG2bds4fvw44N3QvXv3cvjwYQCKi4vp6+tjx44d3pe3cCF5eXls27YNgKysLMrLy6mpqaG7uxuAqqoqdu7cyZEjRwAoKSmhu7ubXbt2AZCfn8/Ro0c5ceIEADk5OZSVlVFdXU1vby8Aq1atoqGhgdbWVgBKS0vp7Oxkz549ABQUFDB79uzoghizZs2itLSULVu2oKqICKtXr6a+vp729nYAysrKaGtro6mpaUz3CbxZFltaWqJzqxQVFSV8n44cOcLMmTMn1X2aN28ekZX3xnKfRISLL754Ut2n8f4/PfXUU9E35Mlyn8b7/3Ts2DFKSkrGdJ9GRFVD2YDrgAdi9m8E7hmU51PAp/10JdAITBup3BUrVuhY2bRpk5fo6VL9GqpfnznmsiYLUc0OYZrdwDSPDqBWh3muhhkaagbyY/bzOD308yHgUQBVrQHOAOaEaJOHNRQbhmFECdMRPA8UiUihiMzAawzeOCjPPuByABG5AM8RHA3LoIoKPzLlkCOIanYI0+wGpjk4QnMEqtoL3Ao8BbyM1zuoQUS+ICJX+dk+DXxYROqB9cAtfhUmFJqbm72EIxPOQYxmhzDNbmCagyPUcQSq+oSqLlHVN6vql/xj/6SqG/10o6q+VVVLVXW5qv4qTHsijVGuTDgHMZodwjS7gWkODqdGFkdxKDRkGIYRD6ccwdKlS72EQ44gqtkhTLMbmObgcMoRpKWleQlHRhVDjGaHMM1uYJqDwylHEBmg4lKNIKrZIUyzG5jm4HDKEURxyBEYhmHEwylHMH/+fC/hUGgoqtkhTLMbmObgcMoRFBYWegmHagRRzQ5hmt3ANAeHU44gMmmVS44gqtkhTLMbmObgcMoRRHFoZLFhGEY8nHIEmZmZXsKhkcVRzQ5hmt3ANAeHU47AJp1zA9PsBqY5OJxyBJFFKVwKDUU1O4RpdgPTHBxOOYLIqlMuhYaimh3CNLuBaQ4OpxxBFIdCQ4ZhGPFwyhFEF352yBHYAt9uYJrdICzNTjmCvXv3egmHRhZHNTuEaXYD0xwcTjmCw4cPewmHagRRzQ5hmt3ANAeHU44gikOOwDAMIx5OOYLi4mIv4VD30ahmhzDNbmCag8MpR9DX1+clHOo+GtXsEKbZDUxzcCTkCERkrYj8o5/OF5EVoVgTMjt27PASDoWGopodwjS7gWkOjriOQES+Bfw58AH/0BvAfaFYkywcCg0ZhmHEIz2BPG9R1TIReRFAVdtEZFI+QRcuXOglHAoNRTU7hGl2A9McHImEhk6KyDRAAUQkF+gPxZqQycvL8xIOhYaimh3CNLuBaQ6ORBzBvcCPgHNE5H8D1cBdoVgTMqdNOueAI7CJudzANLtBWJrjhoZU9SEReQG4AhDgOlXdHoo1ycKhkcWGYRjxiOsIROR7qnoL0DDEsUlFVlaWl3CoRhDV7BCm2Q1Mc3AkEhq6KHbHby/4H6FYEzLl5eVewiFHENXsEKbZDUxzcAzrCETk70WkHbhIRNr8rR14DXgiFGtCJrrws0OhIVvg2w1MsxukYvH6u4BzgLv9v+cAc1R1tqreHoo1IdPd3e0lHKoRRDU7hGl2A9McHMM6AvXo9R/6WUApUCEibxGRtyRSuIisEZEdIrJbRO4YJs/1ItIoIg0i8siYVIwWhxyBYRhGPERVR84g8lfAp4GFwB/w2geeVdVL45yXBuwE3gY0A88D71fVxpg8RcCjwGWq2i4ic1X1yEjllpeXa21tbTxdQ9Lb20t6ejp8Ox+6muHD+yAnf0xlTRaimh3CNLuBaR4dIvKCqg7ZyJBIY/FtQDnQpKp/BqwADiVw3kpgt6ruUdUeYANw9aA8HwbuVdV2gHhOYLzs3LnTSzg0sjiq2SFMsxuY5uBIxLWcUNXjIoKIzFDVBhE5P4HzFgL7Y/abgYpBeZYAiMjvgDTgTlX95eCCRGQdsA5gwYIFbN68GYDFixeTnZ1NfX09ALm5uSxbtoytW7d64tLTqaqqoq6ujo6ODrq6uli0aBGZJ0+QBlTXPEfhBWVkZGSwfbs3NGLu3LksWbKE6upqADIyMqisrKS2tpauri4AKioqaG5u5sCBAwAsXbqUtLQ0Ghu9ys78+fMpLCyMNuxkZmZSUVHBtm3bootPV1ZWsnfv3uhCE8XFxfT19UUnlVq4cCF5eXnRASRZWVmUl5dTU1MTjRNWVVWxc+dOjhzx/GdJSQnd3d3s2rULgPz8fA4dOhT9PCcnh7KyMqqrq+nt7QVg1apVNDQ00NraCkBpaSmdnZ3s2bMHgIKCAmbPnk1dXR0As2bNorS0lC1btqCqiAirV6+mvr6e9vZ2AMrKymhra6OpqWlM9wm83hEtLS3s3+/9hIqKihK+T4cPH+bIkSOT6j7NmzePSE13LPepp6eHvLy8SXWfxvv/tHfv3uh3Olnu03j/n7q6usjKyhrTfRoRVR1xAzYCZwP/AmzCG2X8ywTOuw54IGb/RuCeQXl+DvwEmA4U4jmLs0cqd8WKFTpWNm3a5CW+PlP1a6j2dI25rMlCVLNDmGY3MM2jA6jVYZ6riYwsvspPfl5ELgfO8h/g8WgGYgPwecDBIfI8q6ongb0isgMowmtPCJySkhIv4VD30ahmhzDNbmCag2NUC9Oo6tPAb/DaDeLxPFAkIoX+bKVr8WoXsTyON8U1IjIHL1S0ZzQ2jYbu7m7Qfuj3qnFMm/oNTdbFzg1MsxskvfuoiCwUkXtF5HERuUVEMkXkX4HdwKJ4BatqL3Ar8BTwMvCoeu0LXxCRSC3jKaBVRBrxwk63q2rreEUNx65du6DvpLeTNgNEwrrUhCES33QJ0+wGpjk4RnolfgiowRtF/A7gE8Au4GJVPZBI4ar6BINGIavqP8WkFfiUvyUHh8JChmEYiTCSI5ijqp/z078QkRagUlVPJMGuUMjPz3duMFl+/tQeJzEUptkNTHNwjBgkF5FsvKmnAQ4D0yOrk6lqRygWhci8efOgr9PbccQRzJs3L9UmJB3T7AamOThGaizOxZt6OrLNBhr99KRcj6C2tta50NBYR2FPZkyzG5jm4Bi2RqCqU3MdOMdCQ4ZhGPEYVffRyU5OTo5zjiAnJyfVJiQd0+wGpjk44k46N9EYz6RzALS8CN8vg3OWw00vBmeYYRjGBGa8k85NGaqrq52acA6IzvHiEqbZDUxzcMR1BCJSEOkpJCJVIvJREZmUdbLe3l7nQkORybBcwjS7gWkOjkRqBI8DKiJvxhtkdgGQnAVkwsAxR2AYhhGPRBamqVPVMhG5HehW1W+KyIuqenFyTBzIeNoI+vv7mfbqU/DjK6FgDbz3yYCtm3j09/czbZpTEUDT7AimeXSMt42gV0Suw5tGOjLr6PQxWZJiGhoanKsRNDQ0pNqEpGOa3cA0B0cijuCv8GYIvUtV94hIIbA+FGtCprW11TlHEFkgwyVMsxuY5uBIZD2C7SLyceA8f2Wy3ar6pVCsSQaOjSw2DMOIRyK9hv4Mb+rp/wC+C+wUkbeGbVgYlJaWOlcjKC0tTbUJScc0u4FpDo5EQkN3A1eq6ltV9S3AXwDfCMWakOns7HTOEXR2dqbahKRjmt3ANAdHIo5ghqo2RnZU9WVgUj5F9+zZc8oROBIaiiya7RKm2Q1Mc3AkslZjnYh8G3jY378BmLxzMzg2stgwDCMeidQI/hZ4BfgM8Pd4awr/TZhGhUVBQYFzoaGCgoJUm5B0TLMbmObgiLcwzYXAm4GfqOpdoViQRGbPng0H3QoNzZ49O9UmJB3T7AamOThGWrz+s3jTS9wA/FpE/ioUC5JIXV2dc6Ghurq6VJuQdEyzG5jm4BipRnADcJGqviEi5+AtQv/dUKxIJo6FhgzDMOIxUhtBt6q+AaCqR+PknRTMmjXLOUcwa9asVJuQdEyzG5jm4BipRrBYRH7spwV4c8w+qvqXoVgUIqWlpfAbt9oIbNCNG5hmN0jFgLL3Avf627cG7d8bijUhs2XLFudqBFu2bEm1CUnHNLuBaQ6OkRavfzqUK6YQVXXOEUy2pUiDwDS7gWkOjkkf9x8NIuLcyGIRSbUJScc0u4FpDrDcyeZVx714/U+vgd2Pw1U/hqJrgjPMMAxjAhPI4vUikhGcSamhvr7eudBQfX19qk1IOqbZDUxzcCQyDfVKEfkDsMvfLxWRe0KxJmTa29udCw21t7en2oSkY5rdwDQHRyI1gm8C7wJaAVS1Hm/FssmJYyOLDcMw4pGII5imqq8OOtYXhjFhU1ZW5lxoqKysLNUmJB3T7AamOTgScQT7RWQloCKSJiKfBHYmUriIrBGRHSKyW0TuGCHftSKiIjJkQ0ZQtLW1OecI2traUm1C0jHNbmCagyMRR/AR4FPAIqAFuMQ/NiIikoY38OydQDHwfhEpHiJfNvBxYFviZo+NpqYm59YsbmpqSrUJScc0u4FpDo5EFq8/AqwdQ9kr8Ra63wMgIhuAq4HGQfn+BbgL+LsxXGP0OFYjMAzDiEdcRyAi3wFOG2ygquvinLoQ2B+z3wxUDCr7YiBfVX8uIsM6AhFZB6wDWLBgAZs3bwZg8eLFZGdnR7tU5ebmsmzZMrZu3QpAeno6VVVV1NXV0dHRQU9PD/293UwDnn2+jhMZhygqKiIjI4Pt27cDMHfuXJYsWUJ1dTUAGRkZVFZWUltbS1dXFwAVFRU0Nzdz4MABAJYuXUpaWhqNjZ6Pmz9/PoWFhdTU1ACQmZlJRUUF27Zt4/jx4wBUVlayd+9eDh8+DEBxcTF9fX3s2LHD+/IWLiQvL49t27yKUlZWFuXl5dTU1NDd3Q1AVVUVO3fu5MiRIwCUlJTQ3d3Nrl27AMjPzx/wfeXk5FBWVkZ1dTW9vb0ArFq1ioaGBlpbWwFvLpPOzs7okngFBQXMnj07Ov3trFmzKC0tZcuWLagqIsLq1aupr6+P9mgoKyujra0t+vYy2vsEUF5eTktLC/v3ez+h0dynnp4eNm/ePKnu07x584iMjxnLfcrJyaGjo2NS3afx/j8B0d/2ZLlP4/1/6unpYd++fWO6TyMRd0CZiLwvZvcM4Bpgv6p+LM551wHvUNW/9vdvBFZGzhORacAzwC2q2iQim4G/U9URR4uNZ0BZe3s7sx4tga6DsK4ZsheOqZzJRHt7u3OzNJpmNzDNo2NcA8pU9Ycx24PAX+LF/OPRDOTH7OcBB2P2s4ESYLOINOG1PWwMs8HYBpS5gWl2A9McHGOZa6gQODeBfM8DRSJSKCIz8NoZNkY+VNU/qeocVS1Q1QLgWeCqeDWCceOYIzAMw4hHIm0E7ZxqI5gGtAHDdgWNoKq9InIr8BSQBnxXVRtE5AtArapuHLmE4MnNzXWu11Bubm6qTUg6ptkNTHNwjNhGIN5Ud/nAAf9Qv6Z4lrrxtBH09/cz7evTQfvhtl6YlhawdROP/v5+pk1zapJZ0+wIpnl0jLmNwH/o/0RV+/xtck1VOoitWzZ5TkCmOeEEgGhPApcwzW5gmoMjEdfynIhMibHc09Tr4mXtA4ZhGKcYto1ARNJVtReoAj4sIq8Ab+CtX6yqOumcw/RpfoXGkfYB8PoUu4ZpdgPTHBzDthGISJ2qlonIm4f6XFVfCcWiOIxrYZpjR+H/zYXMOfDRo8EaZhiGMYEZaxuBgPfAH2oLxdKQ+UP9C17CodBQZASjS5hmNzDNwTFSPeMcEfnUcB+q6v8NwZ5QeaPDX9TBodBQZIi5S5hmNzDNwTGSI0gDsvBrBlMB0ZNewqEagWEYRjxGcgSHVPULSbMkCVx4wVJowClHEG+yqamIaXYD0xwccdsIphKtr3kzE7oUGmppaUm1CUnHNLuBaQ6OkRzB5aFcMYUcPdTsJRyqEUSmB3YJ0+wGpjk4hnUEqjrl1oGzNgLDMIzTcWqijvwF87yEQ6GhoqKiVJuQdEyzG5jm4HDKEUxP8wfPOVQjyMjISLUJScc0u4FpDg6nHMH+vf44OIccQWTJQJcwzW5gmoPDKUcQbSNwKDRkGIYRD6ccwdnZM72EQzWCuXPnptqEpGOa3cA0B4dTjmD+ObO9hEOOYMmSJak2IemYZjcwzcHhlCN4ZdfLXsIhR1BdXZ1qE5KOaXYD0xwcTjkC6bc2AsMwjME45QhmRFandKhGYF3s3MA0u4F1Hw2Ac/Pe5CUccgSVlZWpNiHpmGY3MM3B4ZQjONjc5CUcCg2NeTW3SYxpdgPTHBxOOYKT3ce8hEM1gq6urlSbkHRMsxuY5uBwyhFM67dJ5wzDMAbjlCN407xcL7p70hsAABUsSURBVOFQaKiioiLVJiQd0+wGpjk4nHIE0TWLHaoRNDc3p9qEpGOa3cA0B4dTjuBY15+8hEOO4MCBA6k2IemYZjcwzcHhlCOYZgvTGIZhnIZTjiDnzEwv4VAbwdKlS1NtQtIxzW5gmoPDKUfgYo0gLS0tfqYphml2A9McHKE6AhFZIyI7RGS3iNwxxOefEpFGEXlJRJ4WkXPDtKfLwcbixsbGVJuQdEyzG5jm4AjNEYhIGnAv8E6gGHi/iBQPyvYiUK6qFwGPAXeFZQ/E1AgcCg0ZhmHEI8wawUpgt6ruUdUeYANwdWwGVd2kqv5wX54F8kK0h4x0X65DNYL58+en2oSkY5rdwDQHR3oopXosBPbH7DcDI42G+BDw5FAfiMg6YB3AggUL2Lx5MwCLFy8mOzub+vp6AHJzc1m2bBlbt24FID09naqqKurq6ujo6KCs+w3PkENH2L3bK6OoqIiMjIzoWqBz585lyZIl0Xm/MzIyqKyspLa2Njq8u6Kigubm5mhXrqVLl5KWlhatts2fP5/CwkJqamoAyMzMpKKigm3btnH8+HHAmzxq7969HD58GIDi4mL6+vrYsWOH9+UtXEheXh7btm0DICsri/Lycmpqauju7gagqqqKnTt3cuTIEQBKSkro7u5m165dAOTn5zN37tzo95WTk0NZWRnV1dX09vYCsGrVKhoaGmhtbQWgtLSUzs5O9uzZA0BBQQGzZ8+mrq4OgFmzZlFaWsqWLVtQVUSE1atXU19fT3u7F3orKyujra2NpqamMd0ngPLyclpaWti/f/+o71NnZyeHDx+eVPdp3rx50XlkxnKf8vLy6OjomFT3abz/T+3t7dHf9mS5T+P9f1JVZs6cOab7NCKqGsoGXAc8ELN/I3DPMHk/gFcjyIhX7ooVK3SsdNx7nurXUD1cN+YyJhubNm1KtQlJxzS7gWkeHUCtDvNcDbNG0Azkx+znAQcHZxKRK4B/BFaraneI9jjZa8gwDCMeYbYRPA8UiUihiMwA1gIbYzOIyMXAt4GrVPVIiLYAkEafn3DHEWRmZqbahKRjmt3ANAeHeDWGcBCRK4GvA2nAd1X1SyLyBbwqykYR+Q1wIXDIP2Wfql41Upnl5eU65jm57z8XOvfBh5sgJ9SeqoZhGBMKEXlBVYdsLAh1HIGqPqGqS1T1zar6Jf/YP6nqRj99harOU9Xl/jaiExgvPSe8xmKXuo9GGsdcwjS7gWkODqdGFouD6xFEer+4hGl2A9McHG45AmssNgzDOA2nHEG0sdih0JAt8O0GptkNbPH68aKK9Pd46bTpqbUliezduzfVJiQd0+wGpjk43HEE/d7IP6alg7gjOzLS0iVMsxuY5uBw54kYqQ04FBYyDMNIBHccQV8kLOSWIyguHjzh69THNLuBaQ4OcwRTnL6+vlSbkHRMsxuY5uBwzxE4FhqKzL7oEqbZDUxzcLjjCPrdrBEYhmHEwx1H4GhoaOHChak2IemYZjcwzcFhjmCKk5cX6qJvExLT7AamOTjccQSOdh+1ibncwDS7gU06N14crREYhmHEwxzBFCcrKyvVJiQd0+wGpjk43HEEjoaG4i5aPQUxzW5gmoPDHUfgaI2gpqYm1SYkHdPsBqY5OMwRTHG6u7tTbULSMc1uYJqDwz1H4FhoyDAMIx7uOAJHRxZXVVWl2oSkY5rdwDQHhzuOwNHQ0M6dO1NtQtIxzW5gmoMjPZRSJyKOhoaOHDni3HS9pnnicPLkSZqbmzlx4kTgZXd3d/Pyyy8HXu5EJhHNZ5xxBnl5eUyfnvhKjO44AkdDQ4aRSpqbm8nOzqagoAARCbTszs5OsrOzAy1zohNPs6rS2tpKc3MzhYWFCZdroaEpTklJSapNSDqmeeJw4sQJcnNzA3cC4L35ukY8zSJCbm7uqGtg5gimONbFzg0msuYwnAB4b7+ukYjmsXzf7jgCR0cW79q1K9UmJB3T7AYT2fmFhY0jGC+O1ggMw4Cf/OQniAh//OMfo8c2b97Mu971rgH5brnlFh577DHAa+i+4447KCoqoqSkhJUrV/Lkk0+O25Yvf/nLnHfeeSxdupSnnnpqyDzPPPMMZWVllJSUcPPNN9Pb2wtAe3s711xzDRdddBErV65k+/bt47YHzBFMefLz81NtQtIxzW4wml4x69evp6qqig0bNiR8zuc//3kOHTrE9u3b2b59Oz/72c/o7Owci6lRGhsb2bBhAw0NDfzyl7/kox/96GnrEPf393PzzTezYcMGtm/fzrnnnsuDDz4IwN13383y5ct56aWXeOihh/jEJz4xLnsiuNNryNHuo/PmzUu1CUnHNE9Q/i3YtoJos+mnR46bd3V18bvf/Y5NmzZx1VVXceedd8Yt+9ixY3znO99h7969ZGRkAN53fP3114/L5p/+9KesXbuWjIwMCgsLOe+883juueeorKyM5mltbSUjI4MlS5YA8La3vY0vf/nLfOhDH2LHjh189rOfBeD888+nqamJlpaWcd9/d2oEjnYfra2tTbUJScc0G7E8/vjjrFmzhiVLljB79mzq6urinrN7924WLVpETk5O3Ly33XYby5cvP237yle+clreAwcODKi95eXlceDAgQF55syZw8mTJ6P39LHHHmP//v0AFBcX8+Mf/xiA5557jldffZXm5ua4NsbDvRqBY47AMCYMcd7cR0ui4wjWr1/PJz/5SQDWrl3L+vXrKSsrG7Z3zWh73dx9990J5x2q18/g64kIGzZs4LbbbqO7u5u3v/3tpKd7j+rbbruNz33ucyxfvpwLL7yQiy++OPrZeAjVEYjIGuAbQBrwgKp+ZdDnGcBDwAqgFXifqjaFYoyjoaFE3mimGqbZDaZNix/QaG1t5ZlnnmH79u2ICH19fYgId911F7m5ubS3tw/I39bWxpw5czjvvPPYt29fQs7mtttuY9OmTacdX7t2LXfccceAY3l5edG3e/AG3C1YsOC0cysrK/ntb38LwK9+9avo1BJnn302//mf/wl4TqWwsHBUA8eGRVVD2fAe/q8Ai4EZQD1QPCjPR4H7/PRa4Ifxyl2xYoWOiZ/+perXUN3x2NjONwxj1DQ2Nqb0+vfdd5+uW7duwLFVq1bp1q1b9cSJE1pQUBC1sampSRctWqSvv/66qqrefvvtesstt2h3d7eqqh48eFAffvjhcdmzfft2veiii/TEiRO6Z88eLSws1N7e3tPytbS0qKrqiRMn9LLLLtOnn35aVVXb29uj9tx///164403Dnmdob53oFaHea6G2UawEtitqntUtQfYAFw9KM/VwIN++jHgcglr9ImjoaHq6upUm5B0TLMbJNKDZ/369VxzzTUDjr33ve/lkUceISMjg+9///t88IMfZPny5Vx77bU88MADnHXWWQB88Ytf5JxzzqG4uJiSkhLe8573cM4554zL5mXLlnH99ddTXFzMmjVruPfee0lLSwPgyiuv5ODBgwB89atf5YILLuCiiy7i3e9+N5dddhngtQUtW7aM888/nyeffJJvfOMb47IngmhIo/NE5Fpgjar+tb9/I1ChqrfG5Nnu52n291/x87w2qKx1wDqABQsWrPjBD34AwOLFi8nOzqa+vh6A3Nxcli1bxtatWwFIT0+nqqqKuro6Fv7+dmZ1PE/fmh9wcHpxtHpWVFRERkZGtD/u3LlzWbJkSfQfKyMjg8rKSmpra+nq6gKgoqKC5ubmaCPP0qVLSUtLo7GxEYD58+dTWFgYXU0oMzOTiooKtm3bxvHjxwGv6rd3714OHz4MeI1AfX197NixA4CFCxeSl5fHtm3bAG+t0vLycmpqaqKDSqqqqti5cydHjhwBvGkGuru7o4OL8vPzaWpqiv7QcnJyKCsro7q6OtovedWqVTQ0NNDa2gpAaWkpnZ2d7NmzB4CCgoIBDWyzZs2itLSULVu2oKqICKtXr6a+vj5azS4rK6OtrY2mpqZR36eOjg7AW5KvpaVlTPfp8OHDZGVlTar7NG/evGjj4FjuU09PD5dccsmEu0+zZ8/mwgsvjP7viAhZWVm88cYb9Pf3A3DmmWfS09PDyZMno/dSRKLTJKSnp5ORkcEbb7wxoIzXX389+ts+88wz6e7ujn5fZ5xxBqoavQfTp09nxowZ0TKmTZvGmWeeSVdXVzRun5WVxYkTJ0YsY/r06Rw7dmxAGbEOKSsri+PHj0e7hGZmZtLX10dPj/ciOmPGDNLT06NlpKWlMXPmzAFlZGdnc+zYsWgZM2fOpLe3l56eHvr6+sjMzCQtLS36G01LSyMzMzP6HYMXcjp+/PiA+5Sdnf2Cqg691uVwVYXxbsB1eO0Ckf0bgXsG5WkA8mL2XwFyRyp3zKEhVd20adOYz52smGY3mKiawwwNdXR0hFb2RCVRzRMpNNQMxI5yyQMODpdHRNKBs4C2sAxatWpVWEVPWEyzG7ioOSsrK9UmJJ2wNIfpCJ4HikSkUERm4DUGbxyUZyNws5++FnjG91yh0NDQEFbRExbT7AYTWXNY/9KR0IhLJKJ5LN93aI5AVXuBW4GngJeBR1W1QUS+ICJX+dn+A8gVkd3Ap4A7hi4tGCLxVZcwzW4wUTWfccYZtLa2huIMBk/N4ALxNKu/HsFop+gOdRyBqj4BPDHo2D/FpE/gtSUYhjEFycvLo7m5maNHjwZe9okTJ5xbkyARzZEVykaDOyOL8XpauIZpdoOJqnn69OnBDHgagvb2dmbNmhVK2ROVsDS7M9cQifU7nmqYZjcwzW4QlmanHEGkz7VLmGY3MM1uEJZmpxyBYRiGcTqhjSwOCxE5Crw6xtPnAK/FzTW1MM1uYJrdYDyaz1XVIefImHSOYDyISK0ON8R6imKa3cA0u0FYmi00ZBiG4TjmCAzDMBzHNUdwf6oNSAGm2Q1MsxuEotmpNgLDMAzjdFyrERiGYRiDMEdgGIbhOFPSEYjIGhHZISK7ReS0GU1FJENEfuh/vk1ECpJvZbAkoPlTItIoIi+JyNMicm4q7AySeJpj8l0rIioik76rYSKaReR6/143iMgjybYxaBL4bS8SkU0i8qL/+74yFXYGhYh8V0SO+Cs4DvW5iMg3/e/jJREpG/dFh1uxZrJuQBreSmeLgRlAPVA8KM9Hgfv89Frgh6m2Owma/xyY6ac/4oJmP182sBV4FihPtd1JuM9FwIvALH9/bqrtToLm+4GP+OlioCnVdo9T8yqgDNg+zOdXAk8CAlwCbBvvNadijWAlsFtV96hqD7ABuHpQnquBB/30Y8DlIiJJtDFo4mpW1U2qeszffRZvxbjJTCL3GeBfgLuAE8k0LiQS0fxh4F5VbQdQ1SNJtjFoEtGsQI6fPovTV0KcVKjqVkZeqfFq4CH1eBY4W0TeNJ5rTkVHsBDYH7Pf7B8bMo96C+j8CchNinXhkIjmWD6E90YxmYmrWUQuBvJV9efJNCxEErnPS4AlIvI7EXlWRNYkzbpwSETzncAHRKQZb/2TjyXHtJQx2v/3uEzF9QiGerMf3Ec2kTyTiYT1iMgHgHJgdagWhc+ImkVkGnA3cEuyDEoCidzndLzw0KV4tb7fikiJqr4esm1hkYjm9wPfU9V/E5FK4GFfc3/45qWEwJ9fU7FG0Azkx+zncXpVMZpHRNLxqpMjVcUmOoloRkSuAP4RuEpVu5NkW1jE05wNlACbRaQJL5a6cZI3GCf62/6pqp5U1b3ADjzHMFlJRPOHgEcBVLUGOANvcrapSkL/76NhKjqC54EiESkUkRl4jcEbB+XZCNzsp68FnlG/FWaSElezHyb5Np4TmOxxY4ijWVX/pKpzVLVAVQvw2kWuUtXa1JgbCIn8th/H6xiAiMzBCxVN5on7E9G8D7gcQEQuwHMEwa+NOXHYCNzk9x66BPiTqh4aT4FTLjSkqr0icivwFF6Pg++qaoOIfAGoVdWNwH/gVR9349UE1qbO4vGToOavAlnAf/nt4vtU9aqUGT1OEtQ8pUhQ81PA20WkEegDblfVibmyfQIkqPnTwHdE5Da8EMktk/nFTkTW44X25vjtHv8MTAdQ1fvw2kGuBHYDx4APjvuak/j7MgzDMAJgKoaGDMMwjFFgjsAwDMNxzBEYhmE4jjkCwzAMxzFHYBiG4TjmCIxJjYj0icjvY7aCEfIWDDej4yivudmfDbPen8ph6TjLu0VEjvr2/9HvBhnvnEtF5C3jua5hRJhy4wgM5ziuqstTcN0bVLVWRNbhjdEY75iMH6rqrSKSC+wQkcdUdf8I+S8FuoD/Hud1DcNqBMbUw3/z/62I1PnbaW/OIrJMRJ7z38JfEpEi//gHYo5/W0TS4lxuK3Cef+7l/pz4f/DnlM/wj39FTq0F8bWRCvMHf+0G3uSf+27x1sx4UUR+IyLz/FrP3wK3+Xb+mYicIyI/EpHn/e2to/vWDJexGoEx2ckUkd/76b2qeg1wBHibqp7wH/Dr8Sbai+VvgW+o6g/8qQvS/OkJ3ge8VVVPisi/AzcAD41w/XcDfxCRM4DvAZer6k4ReQj4iP/3GuB8VVUROXskMSKyCG+KhJf8Q9XAJf65fw18RlU/LSL3AV2q+jX/vEeAu1W12i/jKeCCEb85w/AxR2BMdoYKDU0HviUiy/GmWVgyxHk1wD+KSB7wY1XdJSKXAyuA5/1pODLxnMpQ/EBEjgNNeNMeL8VzRDv9zx8E/hfwLby1EB4QkV8Aw02J/T4R+XO/nA+ramT9hDzgh+LNNz8D2DvM+VcAxXJqWY0cEclW1c5h8htGFHMExlTkNqAFKMULf562KI2qPiIi24C/AJ7y37YFeFBV/yGBa9wQO4GdH9s/DX+unJV4k6KtBW4FLhsia6SNoBL4hYg8qaqHgXuA/6uqG0XkUry594diGlCpqscTsN0wBmBtBMZU5CzgkD8f/Y14k5UNQEQWA3tU9Zt4szleBDwNXCsic/08syXxtZ3/CBSIyHn+/o3AFhHJAs5S1SeATwIjNmz70yg/DHwiRssBP31zTNZOvKm2I/wKz8lE9KWiAd2YpJgjMKYi/w7cLCLP4oWF3hgiz/uA7X77wvl4S/81Ap8DfiUiLwG/xm+0jYcfyvkg3uyufwD6gfvwHtY/98vbgldbice/Ah8UkWy8GsB/ichvgddi8vwMuCbSWAx8HCj3G6Qb8dpADCMhbPZRwzAMx7EagWEYhuOYIzAMw3AccwSGYRiOY47AMAzDccwRGIZhOI45AsMwDMcxR2AYhuE4/x9Xb/3QwsyO7wAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plotRUC(y_true, y_pred, \"MLP_77\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
